<template>
	<view>
		<slot></slot>
		<view class="overflow fixed" style="left: -999px">
			<!-- #ifdef APP-NVUE -->
			<gcanvas
				id="waterCanvas"
				ref="waterCanvasRef"
				:style="{
					width: `${boxInfo.width}${props.unit}`,
					height: `${boxInfo.height}${props.unit}`
				}"
			></gcanvas>
			<!-- #endif -->
			<!-- #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ -->
			<canvas
				id="waterCanvas"
				type="2d"
				:style="{
					width: `${boxInfo.width}${props.unit}`,
					height: `${boxInfo.height}${props.unit}`
				}"
			></canvas>
			<!-- #endif -->
			<!-- #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ || APP-NVUE -->
			<canvas
				id="waterCanvas"
				canvas-id="waterCanvas"
				:style="{
					width: `${boxInfo.width}${props.unit}`,
					height: `${boxInfo.height}${props.unit}`
				}"
			></canvas>
			<!-- #endif -->
		</view>

		<view :class="props.fullscreen ? 'fixed' : 'absolute'" :style="imageWaterStyle"></view>
	</view>
</template>
<script lang="ts" setup>
/**
 * 水印
 * 给页面或者 组件添加水印。
 */
import { computed, getCurrentInstance, nextTick, onMounted, ref, watch, watchEffect } from 'vue'
// #ifdef APP-NVUE
import { enable, WeexBridge } from '../../tool/gcanvas/index.js'
// #endif
const props = defineProps({
	cross: Boolean,
	debug: Boolean,
	fullscreen: Boolean,
	width: {
		type: Number,
		default: 64
	},
	height: {
		type: Number,
		default: 64
	},
	zIndex: {
		type: Number,
		default: 999
	},
	xGap: {
		type: Number,
		default: 0
	},
	yGap: {
		type: Number,
		default: 0
	},
	yOffset: {
		type: Number,
		default: 0
	},
	xOffset: {
		type: Number,
		default: 0
	},
	rotate: {
		type: Number,
		default: 0
	},
	image: String,
	imageOpacity: { type: Number, default: 1 },
	imageHeight: Number,
	imageWidth: Number,
	content: String,
	selectable: {
		type: Boolean,
		default: true
	},
	fontSize: {
		type: Number,
		default: 14
	},
	fontFamily: String,
	fontStyle: {
		type: String,
		default: 'normal'
	},
	fontVariant: {
		type: String,
		default: ''
	},
	fontWeight: {
		type: Number,
		default: 400
	},
	fontColor: {
		type: String,
		default: 'rgba(128, 128, 128, .3)'
	},
	fontStretch: {
		type: String,
		default: ''
	},
	lineHeight: {
		type: Number,
		default: 14
	},
	unit: {
		type: String,
		default: 'rpx'
	}
})

const proxy = getCurrentInstance()?.proxy ?? null
const waterCanvasRef = ref()
const boxInfo = ref({ width: props.width, height: props.height })
const base64UrlRef = ref()
const imageWaterStyle = computed(() => {
	return {
		zIndex: props.zIndex,
		width: '100%',
		height: '100%',
		pointerEvents: 'none',
		backgroundRepeat: 'repeat',
		top: 0,
		left: 0,
		backgroundSize: props.unit == 'rpx' ? `${uni.upx2px(props.xGap + props.width)} px` : `${props.xGap + props.width} px`,
		backgroundPosition: props.cross
			? `${props.unit == 'rpx' ? uni.upx2px(props.width / 2) : props.width / 2}px ${
					props.unit == 'rpx' ? uni.upx2px(props.height / 2) : props.height / 2
			  }px, 0 0`
			: '',
		backgroundImage: props.cross ? `url(${base64UrlRef.value}), url(${base64UrlRef.value})` : `url(${base64UrlRef.value})`
	}
})

onMounted(() => {
	nextTick(async function () {
		await init()
	})
})
watch(
	() => props,
	async () => {
		await init()
	},
	{ deep: true }
)

async function init() {
	// #ifdef APP-NVUE
	const canvas = enable(waterCanvasRef.value, {
		bridge: WeexBridge
	})
	const ctx = canvas.getContext('2d')
	// #endif
	// #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
	const { ctx, canvas }: any = await mp_init()
	// #endif
	// #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ || APP-NVUE
	const ctx = uni.createCanvasContext('waterCanvas', proxy),
		canvas = null
	// #endif
	const ratio = uni.getSystemInfoSync().pixelRatio
	const {
		xGap,
		yGap,
		width,
		height,
		yOffset,
		xOffset,
		rotate,
		image,
		content,
		fontColor,
		fontStyle,
		fontVariant,
		fontStretch,
		fontWeight,
		fontFamily,
		fontSize,
		lineHeight,
		debug
	} = props

	const canvasWidth = (xGap + (width > 0 ? width : 1)) * ratio
	const canvasHeight = (yGap + (height > 0 ? height : 1)) * ratio
	const canvasOffsetLeft = props.unit == 'rpx' ? uni.upx2px(xOffset * ratio) : xOffset * ratio
	const canvasOffsetTop = props.unit == 'rpx' ? uni.upx2px(yOffset * ratio) : yOffset * ratio
	const canvasWidthPx = props.unit == 'rpx' ? uni.upx2px(canvasWidth) : canvasWidth
	const canvasHeightPx = props.unit == 'rpx' ? uni.upx2px(canvasHeight) : canvasHeight
	boxInfo.value = { width: canvasWidth, height: canvasHeight }

	// #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
	canvas.width = canvasWidthPx
	canvas.height = canvasHeightPx
	// #endif

	if (ctx) {
		ctx.translate(0, 0)
		const markWidth = props.unit == 'rpx' ? uni.upx2px(width * ratio) : width * ratio
		const markHeight = props.unit == 'rpx' ? uni.upx2px(height * ratio) : height * ratio
		if (debug) {
			ctx.strokeStyle = 'grey'
			ctx.strokeRect(0, 0, markWidth, markHeight)
		}
		ctx.rotate(rotate * (Math.PI / 180))
		if (image) {
			const { imageWidth, imageHeight } = props
			// #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
			const imageObj = canvas.createImage()
			imageObj.crossOrigin = 'anonymous'
			imageObj.referrerPolicy = 'no-referrer'
			imageObj.src = image
			imageObj.onload = () => {
				ctx.globalAlpha = props.imageOpacity
				ctx.drawImage(
					imageObj,
					canvasOffsetLeft,
					canvasOffsetTop,
					(props.imageWidth || (imageHeight ? (imageObj.width * imageHeight) / imageObj.height : imageObj.width)) * ratio,
					(props.imageHeight || (imageWidth ? (imageObj.height * imageWidth) / imageObj.width : imageObj.height)) * ratio
				)
				endInit({
					ctx: ctx,
					canvas: canvas ?? null,
					canvasWidthPx: canvasWidthPx,
					canvasHeightPx: canvasHeightPx
				})
			}
			// #endif
			// #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ
			await uni.getImageInfo({
				src: image,
				success: function (img) {
					ctx.globalAlpha = props.imageOpacity
					ctx.drawImage(
						image,
						canvasOffsetLeft,
						canvasOffsetTop,
						(props.imageWidth || (imageHeight ? (img.width * imageHeight) / img.height : img.width)) * ratio,
						(props.imageHeight || (imageWidth ? (img.height * imageWidth) / img.width : img.height)) * ratio
					)
					endInit({
						ctx: ctx,
						canvas: canvas,
						canvasWidthPx: canvasWidthPx,
						canvasHeightPx: canvasHeightPx
					})
				}
			})
			// #endif
		} else if (content) {
			if (debug) {
				ctx.strokeStyle = 'green'
				ctx.strokeRect(0, 0, markWidth, markHeight)
			}
			const fontSizePx = props.unit == 'rpx' ? uni.upx2px(fontSize * ratio) : fontSize * ratio

			const fontLineHeightPx = props.unit == 'rpx' ? uni.upx2px(lineHeight * ratio) : lineHeight * ratio
			const ySize = props.unit == 'rpx' ? uni.upx2px(canvasOffsetTop + lineHeight * ratio) : canvasOffsetTop + lineHeight * ratio
			ctx.font = `${fontStyle} ${fontWeight} ${fontSizePx}px/${fontLineHeightPx}px ${fontStretch} ${fontVariant} ${fontFamily || 'sans-serif'}`
			ctx.fillStyle = fontColor
			ctx.fillText(content, canvasOffsetLeft, ySize)
			endInit({
				ctx: ctx,
				canvas: canvas,
				canvasWidthPx: canvasWidthPx,
				canvasHeightPx: canvasHeightPx
			})
		}
	} else {
	}
}
function endInit({ ctx, canvas, canvasWidthPx, canvasHeightPx }: { ctx: any; canvas: any; canvasWidthPx: any; canvasHeightPx: any }) {
	// #ifdef APP-NVUE
	ctx.draw(false, () => {
		ctx.toTempFilePath(
			0,
			0,
			canvasWidthPx,
			canvasHeightPx,
			canvasWidthPx,
			canvasHeightPx,
			'png',
			1,
			function (res: { errMsg: string; tempFilePath: any }) {
				base64UrlRef.value = res.tempFilePath
			}
		)
	})
	// #endif
	// #ifndef APP-NVUE ||  MP-WEIXIN || MP-ALIPAY || MP-QQ
	ctx.draw(false, () => {
		uni.canvasToTempFilePath({
			width: canvasWidthPx,
			height: canvasHeightPx,
			destWidth: canvasWidthPx,
			destHeight: canvasHeightPx,
			canvasId: 'waterCanvas',
			success: function (res) {
				base64UrlRef.value = res.tempFilePath
			}
		})
	})

	// #endif
	// #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
	base64UrlRef.value = canvas.toDataURL()
	// #endif
}
//支付宝和微信，QQ 支持2d渲染。
function mp_init() {
	return new Promise((resolve, rej) => {
		const query = uni.createSelectorQuery().in(proxy)
		query
			.select('#waterCanvas')
			.fields({
				node: true,
				size: true
			})
			.exec((res) => {
				const canvas = res[0].node
				const ctx = canvas.getContext('2d')
				const dpr = uni.getSystemInfoSync().pixelRatio
				canvas.width = res[0].width * dpr
				canvas.height = res[0].height * dpr
				ctx.scale(dpr, dpr)
				resolve({ ctx, canvas })
			})
	})
}
</script>
